<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>src/animation/class.anim.timeline.js - sceneGraph.js</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.9.1/build/cssgrids/cssgrids-min.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <link rel="stylesheet" href="../assets/css/main.css" id="site_styles">
    <link rel="shortcut icon" type="image/png" href="../assets/favicon.png">
    <script src="http://yui.yahooapis.com/combo?3.9.1/build/yui/yui-min.js"></script>
</head>
<body class="yui3-skin-sam">

<div id="doc">
    <div id="hd" class="yui3-g header">
        <div class="yui3-u-3-4">
            
                <h1><img src="../../logo/logoCGSG_256x57.png" title="sceneGraph.js"></h1>
            
        </div>
        <div class="yui3-u-1-4 version">
            <em>API Docs for: v2.1.0</em>
        </div>
    </div>
    <div id="bd" class="yui3-g">

        <div class="yui3-u-1-4">
            <div id="docs-sidebar" class="sidebar apidocs">
                <div id="api-list">
    <h2 class="off-left">APIs</h2>
    <div id="api-tabview" class="tabview">
        <ul class="tabs">
            <li><a href="#api-classes">Classes</a></li>
            <li><a href="#api-modules">Modules</a></li>
        </ul>

        <div id="api-tabview-filter">
            <input type="search" id="api-filter" placeholder="Type to filter APIs">
        </div>

        <div id="api-tabview-panel">
            <ul id="api-classes" class="apis classes">
            
                <li><a href="../classes/CGSG.html">CGSG</a></li>
            
                <li><a href="../classes/CGSGAccordion.html">CGSGAccordion</a></li>
            
                <li><a href="../classes/CGSGAnimationManager.html">CGSGAnimationManager</a></li>
            
                <li><a href="../classes/CGSGAnimationMethod.html">CGSGAnimationMethod</a></li>
            
                <li><a href="../classes/CGSGBindEntry.html">CGSGBindEntry</a></li>
            
                <li><a href="../classes/CGSGButtonMode.html">CGSGButtonMode</a></li>
            
                <li><a href="../classes/CGSGCollisionGhostOnDemandTester.html">CGSGCollisionGhostOnDemandTester</a></li>
            
                <li><a href="../classes/CGSGCollisionManager.html">CGSGCollisionManager</a></li>
            
                <li><a href="../classes/CGSGCollisionMethod.html">CGSGCollisionMethod</a></li>
            
                <li><a href="../classes/CGSGCollisionRegionTester.html">CGSGCollisionRegionTester</a></li>
            
                <li><a href="../classes/CGSGCollisionTesterFactory.html">CGSGCollisionTesterFactory</a></li>
            
                <li><a href="../classes/CGSGColor.html">CGSGColor</a></li>
            
                <li><a href="../classes/CGSGCSSManager.html">CGSGCSSManager</a></li>
            
                <li><a href="../classes/CGSGDimension.html">CGSGDimension</a></li>
            
                <li><a href="../classes/CGSGEvent.html">CGSGEvent</a></li>
            
                <li><a href="../classes/CGSGEventManager.html">CGSGEventManager</a></li>
            
                <li><a href="../classes/CGSGHandleBox.html">CGSGHandleBox</a></li>
            
                <li><a href="../classes/CGSGImgManager.html">CGSGImgManager</a></li>
            
                <li><a href="../classes/CGSGInterpolator.html">CGSGInterpolator</a></li>
            
                <li><a href="../classes/CGSGInterpolatorLinear.html">CGSGInterpolatorLinear</a></li>
            
                <li><a href="../classes/CGSGInterpolatorTCB.html">CGSGInterpolatorTCB</a></li>
            
                <li><a href="../classes/CGSGKeyFrame.html">CGSGKeyFrame</a></li>
            
                <li><a href="../classes/CGSGMap.html">CGSGMap</a></li>
            
                <li><a href="../classes/CGSGMask.html">CGSGMask</a></li>
            
                <li><a href="../classes/CGSGMaskCache.html">CGSGMaskCache</a></li>
            
                <li><a href="../classes/CGSGMaskClip.html">CGSGMaskClip</a></li>
            
                <li><a href="../classes/CGSGMath.html">CGSGMath</a></li>
            
                <li><a href="../classes/CGSGNode.html">CGSGNode</a></li>
            
                <li><a href="../classes/CGSGNodeButton.html">CGSGNodeButton</a></li>
            
                <li><a href="../classes/CGSGNodeCircle.html">CGSGNodeCircle</a></li>
            
                <li><a href="../classes/CGSGNodeColorPicker.html">CGSGNodeColorPicker</a></li>
            
                <li><a href="../classes/CGSGNodeCurveTCB.html">CGSGNodeCurveTCB</a></li>
            
                <li><a href="../classes/CGSGNodeDomElement.html">CGSGNodeDomElement</a></li>
            
                <li><a href="../classes/CGSGNodeEllipse.html">CGSGNodeEllipse</a></li>
            
                <li><a href="../classes/CGSGNodeImage.html">CGSGNodeImage</a></li>
            
                <li><a href="../classes/CGSGNodeLine.html">CGSGNodeLine</a></li>
            
                <li><a href="../classes/CGSGNodeSlider.html">CGSGNodeSlider</a></li>
            
                <li><a href="../classes/CGSGNodeSliderHandle.html">CGSGNodeSliderHandle</a></li>
            
                <li><a href="../classes/CGSGNodeSprite.html">CGSGNodeSprite</a></li>
            
                <li><a href="../classes/CGSGNodeSquare.html">CGSGNodeSquare</a></li>
            
                <li><a href="../classes/CGSGNodeTabMenu.html">CGSGNodeTabMenu</a></li>
            
                <li><a href="../classes/CGSGNodeText.html">CGSGNodeText</a></li>
            
                <li><a href="../classes/CGSGNodeWebview.html">CGSGNodeWebview</a></li>
            
                <li><a href="../classes/CGSGParticle.html">CGSGParticle</a></li>
            
                <li><a href="../classes/CGSGParticleEmitter.html">CGSGParticleEmitter</a></li>
            
                <li><a href="../classes/CGSGParticleSystem.html">CGSGParticleSystem</a></li>
            
                <li><a href="../classes/CGSGPickNodeMethod.html">CGSGPickNodeMethod</a></li>
            
                <li><a href="../classes/CGSGPosition.html">CGSGPosition</a></li>
            
                <li><a href="../classes/CGSGRegion.html">CGSGRegion</a></li>
            
                <li><a href="../classes/CGSGRotation.html">CGSGRotation</a></li>
            
                <li><a href="../classes/CGSGScale.html">CGSGScale</a></li>
            
                <li><a href="../classes/CGSGSceneGraph.html">CGSGSceneGraph</a></li>
            
                <li><a href="../classes/CGSGSection.html">CGSGSection</a></li>
            
                <li><a href="../classes/CGSGTimeline.html">CGSGTimeline</a></li>
            
                <li><a href="../classes/CGSGTraverser.html">CGSGTraverser</a></li>
            
                <li><a href="../classes/CGSGVector2D.html">CGSGVector2D</a></li>
            
                <li><a href="../classes/CGSGView.html">CGSGView</a></li>
            
                <li><a href="../classes/CGSGWEBVIEWMODE.html">CGSGWEBVIEWMODE</a></li>
            
                <li><a href="../classes/CGSGWrapMode.html">CGSGWrapMode</a></li>
            
                <li><a href="../classes/GLOBAL_CONSTANTS.html">GLOBAL_CONSTANTS</a></li>
            
                <li><a href="../classes/GLOBAL_METHODS.html">GLOBAL_METHODS</a></li>
            
                <li><a href="../classes/GLOBAL_PROPERTIES.html">GLOBAL_PROPERTIES</a></li>
            
                <li><a href="../classes/UTIL_ARRAY.html">UTIL_ARRAY</a></li>
            
                <li><a href="../classes/WUICCGSGNodeImageFactory.html">WUICCGSGNodeImageFactory</a></li>
            
            </ul>

            <ul id="api-modules" class="apis modules">
            
                <li><a href="../modules/Animation.html">Animation</a></li>
            
                <li><a href="../modules/Collision.html">Collision</a></li>
            
                <li><a href="../modules/Math.html">Math</a></li>
            
                <li><a href="../modules/Node.html">Node</a></li>
            
                <li><a href="../modules/ParticleSystem.html">ParticleSystem</a></li>
            
                <li><a href="../modules/Scene.html">Scene</a></li>
            
                <li><a href="../modules/Util.html">Util</a></li>
            
            </ul>
        </div>
    </div>
</div>

            </div>
        </div>
        <div class="yui3-u-3-4">
                <div id="api-options">
        Show:
        <label for="api-show-inherited">
            <input type="checkbox" id="api-show-inherited" checked>
            Inherited
        </label>

        <label for="api-show-protected">
            <input type="checkbox" id="api-show-protected">
            Protected
        </label>

        <label for="api-show-private">
            <input type="checkbox" id="api-show-private">
            Private
        </label>
        <label for="api-show-deprecated">
            <input type="checkbox" id="api-show-deprecated">
            Deprecated
        </label>

    </div>


            <div class="apidocs">
                <div id="docs-main">
                    <div class="content">
                        <h1 class="file-heading">File: src/animation/class.anim.timeline.js</h1>

<div class="file">
    <pre class="code prettyprint linenums">
/*
 * Copyright (c) 2014 Gwennael Buchet
 *
 * License/Terms of Use
 *
 * Permission is hereby granted, free of charge and for the term of intellectual property rights on the Software, to any
 * person obtaining a copy of this software and associated documentation files (the &quot;Software&quot;), to use, copy, modify
 * and propagate free of charge, anywhere in the world, all or part of the Software subject to the following mandatory
 * conditions:
 *
 *   •    The above copyright notice and this permission notice shall be included in all copies or substantial portions
 *   of the Software.
 *
 *  Any failure to comply with the above shall automatically terminate the license and be construed as a breach of these
 *  Terms of Use causing significant harm to Gwennael Buchet.
 *
 *  THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 *  WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 *  OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 *
 *  Except as contained in this notice, the name of Gwennael Buchet shall not be used in advertising or otherwise to promote
 *  the use or other dealings in this Software without prior written authorization from Gwennael Buchet.
 *
 *  These Terms of Use are subject to French law.
 */

&quot;use strict&quot;;

/**
 * @module Animation
 * @class CGSGTimeline
 * @extends {Object}
 * @constructor
 * @param {CGSGNode} parentNode
 * @param {string} attribute string representing the attribute to be animated (eg: &quot;position.x&quot;, &quot;rotation.angle&quot;, ...)
 * @param {string} method A string representing the interpolation method = &quot;linear&quot;
 * @type {CGSGTimeline}
 * @author Gwennael Buchet (gwennael.buchet@gmail.com)
 */
var CGSGTimeline = CGSGObject.extend(
    {
        initialize: function (parentNode, attribute) {

            /**
             * The animated nodes
             * @property parentNode
             * @type {CGSGNode}
             */
            this.parentNode = parentNode;

            /**
             * A string representing the attribute to be animated (eg: &quot;position.x&quot;, &quot;rotation.angle&quot;, &quot;color.g&quot;, ...)
             * The attribute must be a numeric property
             * @property attribute
             * @type {String}
             */
            this.attribute = attribute;

            /**
             * @property _method
             * @type {CGSGInterpolator}
             * @default {CGSGInterpolatorLinear} CGSGAnimationMethod.LINEAR
             * @private
             */
            this._method = CGSGAnimationMethod.LINEAR;

            /**
             * list of the [frame, value] pairs for the animation
             * the index of the list begins at 0, not at the first key frame
             *
             * @property listValues
             * @type {Array}
             */
            this.listValues = [];

            //List of the animation keys
            this._listKeys = [];
            //precomputed values for animation since first key to latest-1.
            //Each  cell contains the step, in pixel, from the previous key to the next one
            this._numberOfFrameBetweenKeys = [];
            //list of interpolation keys used to compute the values between all frames
            this._listErpKeys = [];

            /**
             * Callback on animation start event
             * @property onAnimationStart
             * @type {Function}
             */
            this.onAnimationStart = null;
            /**
             * Callback on animation end event
             * @property onAnimationEnd
             * @type {Function}
             */
            this.onAnimationEnd = null;
            /**
             * Callback on animation event
             * @property onAnimate
             * @type {Function}
             */
            this.onAnimate = null;
        },

        /**
         * Add a new animation key frame to the timeline and sort the timeline by frame number
         * @public
         * @method addKey
         * @param {Number} frame. Must be an integer value.
         * @param {Number} value
         */
        addKey: function (frame, value) {
            this._listKeys.push(new CGSGKeyFrame(frame, {x: value, y: 0}));
            this.sortByFrame(this._listKeys);

            this.listValues.clear();

            //by default, create 1 interpolation key for every animation key
            this.addInterpolationKey(frame, value);
        },

        /**
         * Remove the key at the specified frame
         * @method removeKey
         * @param frame {Number} Must be an integer value.
         */
        removeKey: function (frame) {
            this._removeKeyToList(frame, this._listKeys);
            this._removeKeyToList(frame, this._listErpKeys);

            if (this.getNbKeys() &gt; 1) {
                this._computeNumberOfFrameBetweenKeys();
            }
            this.listValues.clear();
        },

        /**
         * @method removeKeysBetween
         * @param frame1 {number}
         * @param frame2 {number}
         */
        removeKeysBetween: function (frame1, frame2) {
            var k;
            for (k = this._listKeys.length - 1; k &gt;= 0; k--) {
                if (this._listKeys[k].frame &gt;= frame1 &amp;&amp; this._listKeys[k].frame &lt;= frame2) {
                    this._listKeys.without(this._listKeys[k]);
                }
            }

            for (k = this._listErpKeys.length - 1; k &gt;= 0; k--) {
                if (this._listErpKeys[k].frame &gt;= frame1 &amp;&amp; this._listErpKeys[k].frame &lt;= frame2) {
                    this._listErpKeys.without(this._listErpKeys[k]);
                }
            }

            this.listValues.clear();
        },

        addInterpolationKey: function (frame, value) {
            this._removeKeyToList(frame, this._listErpKeys);
            this._listErpKeys.push(new CGSGKeyFrame(frame, {x: value, y: 0}));
            this.sortByFrame(this._listErpKeys);
        },

        removeInterpolationKey: function (frame) {
            this._removeKeyToList(frame, this._listErpKeys);
        },

        _removeKeyToList: function (frame, list) {
            var key = null, k = 0;
            for (k; k &lt; list.length - 1; k++) {
                if (list[k].frame === frame) {
                    key = list[k];
                    break;
                }
            }
            list.without(key);
        },

        /**
         * Remove all keys and values
         * @public
         * @method removeAll
         */
        removeAll: function () {
            this.listValues.clear();
            this._listKeys.clear();
            this._listErpKeys.clear();
            this._numberOfFrameBetweenKeys.clear();
        },

        /**
         * Compute the number of steps between all keys, 2 by 2
         * @private
         * @method _computeNumberOfFrameBetweenKeys
         */
        _computeNumberOfFrameBetweenKeys: function () {
            this._numberOfFrameBetweenKeys.clear();
            var nbFrameInSection = 0, k = 0;
            for (k; k &lt; this._listErpKeys.length - 1; k++) {
                nbFrameInSection = this._listErpKeys[k + 1].frame - this._listErpKeys[k].frame;
                this._numberOfFrameBetweenKeys.push(nbFrameInSection);
            }
        },

        /**
         * @public
         * @method getNbKeys
         * @return {Number} the number of keys in this timeline. Must be an integer value.
         */
        getNbKeys: function () {
            return this._listKeys.length;
        },

        /**
         * Sort the list of keys by frame number
         * @public
         * @method sortByFrame
         */
        sortByFrame: function (list) {
            list.sort(function (a, b) {
                return a.frame - b.frame;
            });
        },

        /**
         * Compute all the values (steps) for the animation of this timeline
         * @public
         * @method compute
         */
        compute: function () {
            //empty the list of values
            this.listValues.clear();
            if (this.getNbKeys() &lt; 1) {
                return;
            }

            this._computeNumberOfFrameBetweenKeys();
            this.listValues = this._method.compute(this._listErpKeys, this._numberOfFrameBetweenKeys);
        },

        /**
         * @method getFirstKey
         * @return {CGSGKeyFrame} the first key frame of this timeline
         */
        getFirstKey: function () {
            if (this.getNbKeys() === 0) {
                return null;
            }

            return this._listKeys[0];
        },

        /**
         * @method getLastKey
         * @return {CGSGKeyFrame} the last key frame of this timeline
         */
        getLastKey: function () {
            if (this.getNbKeys() === 0) {
                return null;
            }

            return this._listKeys[this.getNbKeys() - 1];
        },

        /**
         * Get the value for the frame number passed in parameter
         * @public
         * @method getValue
         * @param {Number} frame the frame bound with the returned value. Must be an integer value.
         * @return {*} Object with 2 properties : frame and value, or undefined
         * If no key is defined, return undefined
         * If there is only one key, returns it&#x27;s value
         * If the frame is before the first key, returns the first key value
         * If the frame is after the last key, returns the last key value
         */
        getValue: function (frame) {
            var nbKeys = this.getNbKeys();

            //if no keys : no animation
            if (nbKeys === 0 &amp;&amp; this.listValues.isEmpty()) {
                return undefined;
            }

            //I have keys, but no precomputed values, so compute values
            if (this.listValues.isEmpty()) {
                if (frame &lt; this._listKeys[0].frame) {
                    return undefined;
                }
                return this.compute();
            }

            //Here, I have precomputed values

            //if frame &lt; first frame, return no value
            if (frame &lt; this._listKeys[0].frame) {
                return undefined;
            }

            //if frame &gt; last frame (ie last key), return last value
            if (frame &gt;= this._listKeys[this._listKeys.length - 1].frame) {
                return this.listValues[this.listValues.length - 1].x;
            }

            return this.listValues[frame - this._listKeys[0].frame].x;
        },

        /**
         * Return the precomputed array of values for this timeline
         * @method exportValues
         * @return {Array}
         */
        exportValues: function () {
            if (this.listValues.length === 0) {
                this.compute();
            }

            var values = [], i;
            for (i = 0; i &lt; this.listValues.length; i++) {
                values.push(this.listValues[i]);
            }
            return values;
        },

        /**
         * Import new precomputed values for this timeline.
         * The number of values must match the number of frame defined by the keys of this timeline
         * @method importValues
         * @param newValues {Array} of new values
         * @param startFrame {Number} Must be an integer value.
         */
        importValues: function (newValues, startFrame) {
            this.addKey(startFrame, newValues[0]);
            this.addKey(startFrame + newValues.length - 1, newValues[newValues.length - 1]);
            var i;
            for (i = 0; i &lt; newValues.length; i++) {
                this.listValues.push(newValues[i]);
            }
        }
    }
);

    </pre>
</div>

                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="../assets/js/yui-prettify.js"></script>
<script src="../assets/../api.js"></script>
<script src="../assets/js/api-filter.js"></script>
<script src="../assets/js/api-list.js"></script>
<script src="../assets/js/api-search.js"></script>
<script src="../assets/js/apidocs.js"></script>
</body>
</html>
